#include "hud.hpp"

static const int COLS = 32;
static const int ROWS = 3;

static const int TILES[HeadsUpDisp::ELEMCT] =
{
0, 	0, 	0, 	0,
0x82, 	0xdc,
0x80, 	0x85, 	0x86,	0x87,	0x88,	0xc0
};

static const int LIMITS[HeadsUpDisp::NUMGAUGECT] =
{
99, 	999999,	99,	999999, 
16,	16
};

#include "vec.hpp"

static const Vec2i POSES[HeadsUpDisp::ELEMCT] = 
{
Vec2i(2, 2),	Vec2i(0, 0),	Vec2i(15, 0),	Vec2i(19, 0),
Vec2i(5, 1),	Vec2i(26, 1),
Vec2i(0, 1),	Vec2i(14, 0),	Vec2i(14, 1),	Vec2i(17, 1),	Vec2i(15, 1),
Vec2i(28, 1)
};

static const Vec2i SIZES[HeadsUpDisp::ELEMCT] = 
{
Vec2i(3, 1),	Vec2i(12, 1),	Vec2i(2, 1),	Vec2i(13, 1),
Vec2i(8, 2),	Vec2i(-8, 2),
Vec2i(2, 2),	Vec2i(1, 1),	Vec2i(1, 2),	Vec2i(1, 2),	Vec2i(2, 2),
Vec2i(4, 2)
};

static const wchar_t *FORMSTRS[HeadsUpDisp::NUMCT] =
{
L"=%02i", 	L"SCORE=%06i",	L"=%02i",	L"EXTEND=%06i"
};

#include "image.hpp"

static Image *img;

bool HeadsUpDisp::Open()
{
	img = AllImgs.Get("font");
	return img != 0;
}

void HeadsUpDisp::Init()
{
	grid.Resize(COLS, ROWS);

	int ic;
	for (ic = ICON; ic < ICON_SHOT; ++ic)
	{
		IconSet(ic, 0);
	}

	for ( ; ic < ELEMCT; ++ic)
	{
		IconSet(ic, -1);
	}
}

#include <algorithm>

void HeadsUpDisp::Update()
{
	int el;

	for (el = 0; el < NUMGAUGECT; ++el)
	{
		if (drawvals[el] > vals[el])
		{
			drawvals[el] = std::max(0, drawvals[el] - 1);
		}
		else if (drawvals[el] < vals[el])
		{
			drawvals[el] = std::min(drawvals[el] + 1, LIMITS[el]);
		}
	}

	for (el = 0; el < NUMCT; ++el)
	{
		const Vec2i & pos = POSES[el];
		grid.Printf(pos.x, pos.y, FORMSTRS[el], drawvals[el]);
	}

	for ( ; el < NUMGAUGECT; ++el)
	{
		const Vec2i & pos = POSES[el];
		int glen = SIZES[el].x;
		int gval = drawvals[el];

		for (int c = 0; c != glen; c += (glen < 0) ? -1 : 1)
		{
			int tile = TILES[el];

			if (gval > 1)
				tile += 2;
			else if (gval == 1)
				++tile;

			for (int r = 0; r < SIZES[el].y; ++r)
			{
				grid.Put(pos.x + c, pos.y + r, tile);
				tile += img->Cols();
			}

			gval -= 2;
		}
	}
}

#include "video.hpp"
#include "camera.hpp"

void HeadsUpDisp::Out(float upfrac)
{
	Vid.Look(0, 0);
	Vid.Pos((Cam.size.x - COLS) * .5f, Cam.size.y - ROWS);
	Vid.Pri(1);
	Vid.Flip(false, false);
	Vid.Color(1, 1, 1, 1);
	Vid.TilesDraw(*img, grid.Data(), grid.Cols(), grid.Rows());
}

void HeadsUpDisp::Put(int elem, int val)
{
	vals[elem] = val;
	//if (std::abs(drawvals[elem] - vals[elem]) > 9)
		drawvals[elem] = vals[elem];
}

void HeadsUpDisp::IconSet(int icon, int n)
{
	if (icon < ICON || icon >= ELEMCT)
		return;

	const Vec2i & size = SIZES[icon];
	bool zero = n < 0;
	int tile = zero ? 0 : TILES[icon] + (n * size.x);

	const Vec2i & pos = POSES[icon];
	for (int r = 0; r < size.y; ++r)
	{
		for (int c = 0; c < size.x; ++c)
		{
			grid.Put(pos.x + c, pos.y + r, tile);
			if (!zero)
				++tile;
		}

		if (!zero)
		{
			tile += img->Cols() - size.x;
		}
	}
}

HeadsUpDisp HUD;
